package com.example.matchingengine.service;

import com.example.matchingengine.config.TopicConfig;
import com.example.matchingengine.model.Order;
import com.example.matchingengine.service.model.OrderBook;
import com.example.matchingengine.service.model.OrderBookSnapshot;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 撮合引擎服务
 * 实现高性能订单撮合逻辑
 * 支持WAL（预写日志）和快照持久化，确保数据安全
 */
@Slf4j
@Service
public class MatchingEngineService {

    @Value("#{'${matching-engine.engine.symbols}'.split(',')}")
    private List<String> symbols;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private MeterRegistry meterRegistry;

    @Autowired
    private PersistenceService persistenceService;

    @Autowired
    private TopicConfig topicConfig;
    
    @Autowired
    private ObjectMapper objectMapper;

    // 计时器 - 订单处理时间
    private Timer orderProcessingTimer;

    // 计数器 - 订单数量
    private Counter orderCounter;

    // 计数器 - 成交数量
    private Counter tradeCounter;

    // 订单簿 - 按交易对存储买卖盘
    private final Map<String, OrderBook> orderBooks = new ConcurrentHashMap<>();

    // 读写锁 - 保护订单簿操作
    private final ReentrantReadWriteLock orderBooksLock = new ReentrantReadWriteLock();

    @PostConstruct
    public void init() {
        // 初始化监控指标
        orderProcessingTimer = Timer.builder("matching.engine.order.processing")
                .description("订单处理时间")
                .register(meterRegistry);

        orderCounter = Counter.builder("matching.engine.order.count")
                .description("订单数量")
                .register(meterRegistry);

        tradeCounter = Counter.builder("matching.engine.trade.count")
                .description("成交数量")
                .register(meterRegistry);

        // 初始化订单簿
        initializeOrderBooks();

        log.info("撮合引擎初始化完成，支持的交易对: {}, 持久化已{}, WAL已{}",
                symbols,
                persistenceService.isPersistenceEnabled() ? "启用" : "禁用",
                persistenceService.isWalEnabled() ? "启用" : "禁用");
    }

    /**
     * 初始化订单簿
     */
    private void initializeOrderBooks() {
        // 尝试从持久化文件恢复订单簿
        Map<String, OrderBookSnapshot> snapshots = persistenceService.loadOrderBooksFromDisk();
        
        if (snapshots != null && !snapshots.isEmpty()) {
            // 从快照恢复订单簿
            restoreOrderBooksFromSnapshots(snapshots);
            
            // 应用WAL日志进行增量恢复
            persistenceService.applyWalLogs(orderBooks);
        } else {
            // 创建新的订单簿
            createNewOrderBooks();
        }
    }

    /**
     * 从快照恢复订单簿
     */
    private void restoreOrderBooksFromSnapshots(Map<String, OrderBookSnapshot> snapshots) {
        for (Map.Entry<String, OrderBookSnapshot> entry : snapshots.entrySet()) {
            String symbol = entry.getKey();
            OrderBookSnapshot snapshot = entry.getValue();

            // 检查该交易对是否在配置的支持列表中
            if (!symbols.contains(symbol)) {
                log.warn("跳过未配置的交易对订单簿恢复: {}", symbol);
                continue;
            }

            // 创建订单簿并从快照恢复
            OrderBook orderBook = new OrderBook(symbol);
            orderBook.setDependencies(rocketMQTemplate, tradeCounter, objectMapper, persistenceService, topicConfig);
            orderBook.restoreFromSnapshot(snapshot);
            orderBooks.put(symbol, orderBook);
            
            // 消费者将由DynamicOrderConsumerService自动创建

            log.info("已恢复交易对 {} 的订单簿，买单: {}，卖单: {}",
                    symbol, snapshot.getBuyOrders().size(), snapshot.getSellOrders().size());
        }
    }

    /**
     * 创建新的订单簿
     */
    private void createNewOrderBooks() {
        for (String symbol : symbols) {
            OrderBook orderBook = new OrderBook(symbol);
            orderBook.setDependencies(rocketMQTemplate, tradeCounter, objectMapper, persistenceService, topicConfig);
            orderBooks.put(symbol, orderBook);
        }
        log.info("创建了{}个新的订单簿", symbols.size());
    }

    /**
     * 定时持久化订单簿到磁盘
     * 默认每分钟执行一次
     */
    @Scheduled(fixedDelayString = "${matching-engine.persistence.interval-ms:60000}")
    public void persistOrderBooks() {
        persistenceService.persistOrderBooksData(orderBooks, orderBooksLock);
    }


    /**
     * 取消订单
     */
    public void cancelOrder(String orderId, String symbol) {
        // 获取对应的订单簿
        OrderBook orderBook = orderBooks.get(symbol);
        if (orderBook == null) {
            log.error("不支持的交易对: {}", symbol);
            return;
        }

        // 获取写锁，保证数据一致性
        orderBooksLock.writeLock().lock();
        try {
            // 查找并取消订单
            Order canceledOrder = orderBook.findAndCancelOrder(orderId);
            if (canceledOrder != null) {
                // 记录订单取消到WAL日志
                if (persistenceService.isWalEnabled()) {
                    try {
                        String orderJson = objectMapper.writeValueAsString(canceledOrder);
                        persistenceService.writeWalLog("REMOVE_ORDER", orderJson);
                    } catch (Exception e) {
                        log.error("记录订单取消到WAL日志失败: {}", e.getMessage(), e);
                    }
                }

                // 发送订单状态更新消息
                orderBook.sendOrderStatusUpdate(canceledOrder);
                log.info("订单已取消: {}", orderId);
            } else {
                log.warn("未找到要取消的订单: {}", orderId);
            }
        } finally {
            orderBooksLock.writeLock().unlock();
        }
    }



    /**
     * 处理订单
     * 单线程处理模型，避免锁竞争
     */
    public void processOrder(Order order) {
        // 记录订单计数
        orderCounter.increment();

        // 使用计时器记录处理时间
        orderProcessingTimer.record(() -> {
            // 获取对应的订单簿
            OrderBook orderBook = orderBooks.get(order.getSymbol());
            if (orderBook == null) {
                log.error("不支持的交易对: {}", order.getSymbol());
                return;
            }

            // 记录订单添加到WAL日志
            if (persistenceService.isWalEnabled()) {
                try {
                    String orderJson = objectMapper.writeValueAsString(order);
                    persistenceService.writeWalLog("ADD_ORDER", orderJson);
                } catch (Exception e) {
                    log.error("记录订单到WAL日志失败: {}", e.getMessage(), e);
                }
            }

            // 获取写锁，保证数据一致性
            orderBooksLock.writeLock().lock();
            try {
                // 执行撮合
                orderBook.matchOrder(order);
            } finally {
                orderBooksLock.writeLock().unlock();
            }
        });
    }
}